/*
 * Copyright (c) 2009
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dcarew.hudson;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;

// TODO: support hyperlinks in tooltips for build failures (use the ToolTip class)

// TODO: support hyperlinks in notification windows for build failures

// TODO: clean up all the communications / modeling code

// TODO: the build queue can be accessed at /queue/api/xml


/**
 * The plugin class for the Hudson status project.
 * 
 * @author Devon Carew
 */
public class HudsonPlugin
	extends AbstractUIPlugin
{
	public static final String PLUGIN_ID 			= "org.dcarew.hudson";
	
	public static final String HUDSON_XML_API		= "api/xml";
	
	private static HudsonPlugin	plugin;
	
	
	public HudsonPlugin()
	{
		
	}
	
	public void start(BundleContext context)
		throws Exception
	{
		plugin = this;
		
		super.start(context);
		
		HudsonUpdateJob statusJob = new HudsonUpdateJob();
		
		statusJob.schedule(15000);
	}
	
	public void stop(BundleContext context)
		throws Exception
	{
		plugin = null;
		
		super.stop(context);
	}
	
	public static void log(Throwable exception)
	{
		log(new Status(IStatus.ERROR, PLUGIN_ID, exception.getMessage(), exception));
	}
	
	public static void log(IStatus status)
	{
		getPlugin().getLog().log(status);
	}
	
	/**
	 * Returns the shared instance
	 * 
	 * @return the shared instance
	 */
	public static HudsonPlugin getPlugin()
	{
		return plugin;
	}
	
	/**
	 * @return the version of the Hudson plugin
	 */
	public static String getVersion()
	{
		return (String)getPlugin().getBundle().getHeaders().get(Constants.BUNDLE_VERSION);	
	}
	
	/**
	 * Returns an image descriptor for the image file at the given plug-in relative path.
	 * 
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getImageDescriptor(String path)
	{
		return imageDescriptorFromPlugin(PLUGIN_ID, path);
	}
	
    /**
     * Get an image given a path relative to this plugin.
     * 
     * @param path
     * @return
     */
    public static Image getImage(String path)
    {
        if (getPlugin().getImageRegistry().get(path) != null)
            return getPlugin().getImageRegistry().get(path);

        ImageDescriptor descriptor = findImageDescriptor(path);

        if (descriptor != null)
        {
            getPlugin().getImageRegistry().put(path, descriptor);

            return getPlugin().getImageRegistry().get(path);
        }

        return null;
    }
    
    /**
	 * Returns an image descriptor for the image file at the given plug-in relative path.
	 * 
	 * @param path the path
	 * @return the image descriptor
	 */
	public static ImageDescriptor getBundledImageDescriptor(String path)
	{
		return AbstractUIPlugin.imageDescriptorFromPlugin(PLUGIN_ID, path);
	}

    /**
	 * Respects images residing in any plug-in. If path is relative, then this bundle is looked up
	 * for the image, otherwise, for absolute path, first segment is taken as id of plug-in with
	 * image
	 * 
	 * @param path the path to image, either absolute (with plug-in id as first segment), or
	 *        relative for bundled images
	 * @return the image descriptor
	 */
	public static ImageDescriptor findImageDescriptor(String path)
	{
		final IPath p = new Path(path);
		
		if (p.isAbsolute() && p.segmentCount() > 1)
		{
			return AbstractUIPlugin.imageDescriptorFromPlugin(
				p.segment(0), p.removeFirstSegments(1).makeAbsolute().toString());
		}
		else
		{
			return getBundledImageDescriptor(p.makeAbsolute().toString());
		}
	}

	// User credentials section.
	
	private static final URL 	AUTH_URL;
	
	private static final String AUTH_PASSWORD 	= "org.dcarew.hudson.password"; 
	private static final String AUTH_USERNAME 	= "org.dcarew.hudson.username"; 
	
	static
	{
		try
		{
			AUTH_URL = new URL("http://org.dcarew.hudson/");
		}
		catch (MalformedURLException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	public static HudsonCredentials getUserCredentials()
	{
		Map authMap = Platform.getAuthorizationInfo(AUTH_URL, "", "");
		
		if (authMap == null)
			return null;
		
		String userName = (String)authMap.get(AUTH_USERNAME);
		String password = (String)authMap.get(AUTH_PASSWORD);
		
		return new HudsonCredentials(userName, password);
	}
	
	public static void setUserCredentials(String userName, String password)
	{
		if (userName == null)
			throw new IllegalArgumentException();
		
		if (password == null)
			throw new IllegalArgumentException();
		
		Map authMap = Platform.getAuthorizationInfo(AUTH_URL, "", "");
		
		if (authMap == null)
			authMap = new HashMap();
		
		authMap.put(AUTH_USERNAME, userName);
		authMap.put(AUTH_PASSWORD, password);
		
		try
		{
			Platform.addAuthorizationInfo(AUTH_URL, "", "", authMap);
		}
		catch (CoreException e)
		{
			log(e);
		}
	}
    
	public static String getBaseURL()
	{
		if (getPlugin() == null)
			return null;
		
		return getPlugin().getPreferenceStore().getString("url");
	}
	
	public static void setBaseURL(String baseURL)
	{
		getPlugin().getPreferenceStore().setValue("url", baseURL);
	}
	
	public static boolean getAllowSelfSigned()
	{
		return getPlugin().getPreferenceStore().getBoolean("selfSigned");
	}
	
	public static void setAllowSelfSigned(boolean value)
	{
		getPlugin().getPreferenceStore().setValue("selfSigned", value);
	}
	
	public static String getHudsonView()
	{
		return getPlugin().getPreferenceStore().getString("hudsonView");
	}
	
	public static void setHudsonView(String view)
	{
		getPlugin().getPreferenceStore().setValue("hudsonView", view);
	}
	
	public static boolean getDontNotify()
	{
		return getPlugin().getPreferenceStore().getBoolean("dontNotify");
	}
	
	public static void setDontNotify(boolean value)
	{
		getPlugin().getPreferenceStore().setValue("dontNotify", value);
	}
	
}
